import tkinter as tk
from tkinter import ttk
from config import DEFAULT_TEXT, DEFAULT_FONT_SIZE
import os


class UIBuilder:
    """UI构建相关功能"""
    
    def __init__(self, app):
        self.app = app

    def build_ui(self):
        """构建主界面"""
        self.app.root.geometry("1300x820")
        
        # 创建主容器，使用固定布局
        main_container = tk.Frame(self.app.root)
        main_container.pack(fill=tk.BOTH, expand=True)
        
        # 构建右侧控制面板 - 先创建，固定宽度
        self._build_control_panel(main_container)
        
        # 构建画布区域 - 填充剩余空间
        canvas_container = tk.Frame(main_container, bg="#e8e8e8", relief="sunken", bd=1)
        canvas_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(5, 0), pady=5)
        
        # 添加画布标题
        canvas_title = tk.Label(canvas_container, text="图像编辑区域", font=("Arial", 10, "bold"), 
                               bg="#e8e8e8", fg="#333333", height=2)
        canvas_title.pack(fill="x", padx=2, pady=(2, 0))
        
        # 创建画布框架
        canvas_frame = tk.Frame(canvas_container, bg="#e8e8e8")
        canvas_frame.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
        
        # 创建带滚动条的画布
        self.app.canvas = tk.Canvas(canvas_frame, bg="#ddd", highlightthickness=0, relief="flat")
        
        # 添加滚动条
        h_scrollbar = tk.Scrollbar(canvas_frame, orient="horizontal", command=self.app.canvas.xview)
        v_scrollbar = tk.Scrollbar(canvas_frame, orient="vertical", command=self.app.canvas.yview)
        
        self.app.canvas.configure(xscrollcommand=h_scrollbar.set, yscrollcommand=v_scrollbar.set)
        
        # 布局画布和滚动条
        self.app.canvas.grid(row=0, column=0, sticky="nsew")
        h_scrollbar.grid(row=1, column=0, sticky="ew")
        v_scrollbar.grid(row=0, column=1, sticky="ns")
        
        # 配置grid权重
        canvas_frame.grid_rowconfigure(0, weight=1)
        canvas_frame.grid_columnconfigure(0, weight=1)

    def _build_control_panel(self, parent):
        """构建右侧控制面板 - 统一界面"""
        # 创建主控制面板，固定在右侧，进一步增加宽度
        main_frame = tk.Frame(parent, width=500, bg="#f0f0f0", relief="raised", bd=1)
        main_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=0, pady=0)  # 完全去除边距
        main_frame.pack_propagate(False)  # 保持固定宽度
        
        # 添加标题
        title_frame = tk.Frame(main_frame, bg="#e0e0e0", height=30)
        title_frame.pack(fill="x", padx=1, pady=(1, 0))  # 减少边距
        title_frame.pack_propagate(False)
        
        title_label = tk.Label(title_frame, text="标注控制面板", font=("Arial", 10, "bold"), 
                              bg="#e0e0e0", fg="#333333")
        title_label.pack(expand=True)
        
        # 创建左右分栏布局
        content_frame = tk.Frame(main_frame, bg="#f0f0f0")
        content_frame.pack(fill="both", expand=True, padx=1, pady=1)
        
        # 左侧：控制设置区域 - 增加宽度
        left_frame = tk.Frame(content_frame, bg="#f0f0f0", width=280)
        left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 2))
        left_frame.pack_propagate(False)  # 保持固定宽度
        
        # 创建左侧可滚动区域
        left_canvas = tk.Canvas(left_frame, bg="#f0f0f0", highlightthickness=0, relief="flat")
        left_scrollbar = tk.Scrollbar(left_frame, orient="vertical", command=left_canvas.yview)
        left_scrollable = tk.Frame(left_canvas, bg="#f0f0f0")
        
        def _configure_left_scroll(event):
            left_canvas.configure(scrollregion=left_canvas.bbox("all"))
        left_scrollable.bind("<Configure>", _configure_left_scroll)
        
        left_canvas.create_window((0, 0), window=left_scrollable, anchor="nw")
        left_canvas.configure(yscrollcommand=left_scrollbar.set)
        
        # 左侧内容：设置区域
        self._build_text_settings(left_scrollable)
        
        # 布局左侧滚动组件
        left_canvas.pack(side="left", fill="both", expand=True)
        left_scrollbar.pack(side="right", fill="y")
        
        # 右侧：列表管理区域
        right_frame = tk.Frame(content_frame, bg="#f0f0f0")
        right_frame.pack(side=tk.RIGHT, fill="both", expand=True)
        
        # 右侧内容：3个列表
        self._build_manage_settings(right_frame)
        
        # 绑定鼠标滚轮 - 只在左侧控制面板内有效
        def _on_left_mousewheel(event):
            # 检查鼠标是否在左侧控制面板内
            widget = event.widget
            while widget:
                if widget == left_frame:
                    left_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
                    break
                widget = widget.master
        
        # 绑定到左侧控制面板及其子组件
        def _bind_mousewheel(widget):
            widget.bind("<MouseWheel>", _on_left_mousewheel)
            for child in widget.winfo_children():
                _bind_mousewheel(child)
        
        _bind_mousewheel(left_frame)

    def _build_text_settings(self, parent):
        """构建样式设置面板 - 紧凑布局"""
        # 样式设置 - 融合所有文字相关设置
        style_frame = tk.LabelFrame(parent, text="样式设置", padx=3, pady=3)
        style_frame.pack(fill="x", pady=2)
        
        # 文字内容 - 紧凑布局
        content_row = tk.Frame(style_frame)
        content_row.pack(fill="x", pady=1)
        tk.Label(content_row, text="内容:", width=6, anchor="w").pack(side=tk.LEFT)
        self.app.text_var = tk.StringVar(value=DEFAULT_TEXT)
        self.app.text_entry = tk.Entry(content_row, textvariable=self.app.text_var, font=("Arial", 9))
        self.app.text_entry.pack(side=tk.LEFT, fill="x", expand=True, padx=(2, 0))
        self.app.text_entry.bind("<KeyRelease>", lambda e: self.app.event_handlers.update_selected_label())
        
        # 字体选择 - 紧凑布局
        font_row = tk.Frame(style_frame)
        font_row.pack(fill="x", pady=1)
        tk.Label(font_row, text="字体:", width=6, anchor="w").pack(side=tk.LEFT)
        self.app.font_var = tk.StringVar()
        self.app.font_combo = ttk.Combobox(font_row, textvariable=self.app.font_var, 
                                          values=self._get_font_names(), state="readonly", height=8)
        self.app.font_combo.pack(side=tk.LEFT, fill="x", expand=True, padx=(2, 2))
        self.app.font_combo.bind("<<ComboboxSelected>>", lambda e: self.app.event_handlers.update_selected_label())
        
        # 添加字体按钮 - 小尺寸
        tk.Button(font_row, text="添加", command=self._add_custom_font,
                 bg="#FF9800", fg="white", width=6, font=("Arial", 8)).pack(side=tk.RIGHT)
        
        # 设置默认字体
        if self.app.current_font_path:
            font_name = os.path.basename(self.app.current_font_path)
            self.app.font_var.set(font_name)
        
        # 字号、加粗、颜色 - 一行显示
        props_row = tk.Frame(style_frame)
        props_row.pack(fill="x", pady=1)
        
        # 字号
        tk.Label(props_row, text="字号:", width=6, anchor="w").pack(side=tk.LEFT)
        self.app.size_var = tk.IntVar(value=DEFAULT_FONT_SIZE)
        self.app.size_spin = tk.Spinbox(props_row, from_=8, to=200, 
                                       textvariable=self.app.size_var, width=6, font=("Arial", 9))
        self.app.size_var.trace('w', lambda *args: self.app.event_handlers.update_selected_label())
        self.app.size_spin.pack(side=tk.LEFT, padx=(2, 8))
        
        # 加粗
        self.app.bold_var = tk.BooleanVar(value=False)
        self.app.bold_check = tk.Checkbutton(props_row, text="加粗", 
                                            variable=self.app.bold_var,
                                            command=self.app.event_handlers.update_selected_label,
                                            font=("Arial", 9))
        self.app.bold_check.pack(side=tk.LEFT, padx=(0, 8))
        
        # 颜色预览和选择
        self.app.color_preview = tk.Label(props_row, text="颜色", bg="#000000", 
                                         fg="white", relief="raised", width=8, font=("Arial", 8))
        self.app.color_preview.pack(side=tk.LEFT, padx=(0, 2))
        
        tk.Button(props_row, text="选择", command=self.app.choose_color, 
                 width=6, font=("Arial", 8)).pack(side=tk.LEFT)
        
        # 线条设置 - 新增区域
        line_frame = tk.LabelFrame(parent, text="线条设置", padx=3, pady=3)
        line_frame.pack(fill="x", pady=2)
        
        # 线条类型选择
        type_row = tk.Frame(line_frame)
        type_row.pack(fill="x", pady=1)
        tk.Label(type_row, text="类型:", width=6, anchor="w").pack(side=tk.LEFT)
        
        self.app.line_type_var = tk.StringVar(value="straight")
        tk.Radiobutton(type_row, text="直线", variable=self.app.line_type_var, 
                      value="straight", font=("Arial", 9),
                      command=self.app.event_handlers.update_selected_line).pack(side=tk.LEFT, padx=(2, 8))
        tk.Radiobutton(type_row, text="折线", variable=self.app.line_type_var, 
                      value="polyline", font=("Arial", 9),
                      command=self.app.event_handlers.update_selected_line).pack(side=tk.LEFT)
        
        # 线条粗细和颜色
        line_props_row = tk.Frame(line_frame)
        line_props_row.pack(fill="x", pady=1)
        
        tk.Label(line_props_row, text="粗细:", width=6, anchor="w").pack(side=tk.LEFT)
        self.app.line_width_var = tk.IntVar(value=2)
        self.app.line_width_spin = tk.Spinbox(line_props_row, from_=1, to=20,
                                             textvariable=self.app.line_width_var, 
                                             width=4, font=("Arial", 9))
        # 绑定线条粗细变化事件
        self.app.line_width_var.trace('w', lambda *args: self.app.event_handlers.update_selected_line())
        self.app.line_width_spin.pack(side=tk.LEFT, padx=(2, 8))
        
        # 线条颜色
        self.app.line_color_preview = tk.Label(line_props_row, text="线色", bg="#000000", 
                                              fg="white", relief="raised", width=6, font=("Arial", 8))
        self.app.line_color_preview.pack(side=tk.LEFT, padx=(0, 2))
        
        tk.Button(line_props_row, text="选择", command=self._choose_line_color, 
                 width=6, font=("Arial", 8)).pack(side=tk.LEFT)
        
        # 遮罩设置 - 新增区域
        mask_frame = tk.LabelFrame(parent, text="遮罩设置", padx=3, pady=3)
        mask_frame.pack(fill="x", pady=2)
        
        # 遮罩透明度和颜色
        mask_props_row = tk.Frame(mask_frame)
        mask_props_row.pack(fill="x", pady=1)
        
        tk.Label(mask_props_row, text="透明度:", width=8, anchor="w").pack(side=tk.LEFT)
        self.app.mask_opacity_var = tk.DoubleVar(value=0.5)
        self.app.mask_opacity_scale = tk.Scale(mask_props_row, from_=0.1, to=1.0, 
                                              resolution=0.1, orient=tk.HORIZONTAL,
                                              variable=self.app.mask_opacity_var,
                                              command=lambda v: self.app.update_selected_mask())
        self.app.mask_opacity_scale.pack(side=tk.LEFT, fill="x", expand=True, padx=(2, 8))
        
        # 遮罩颜色
        self.app.mask_color_preview = tk.Label(mask_props_row, text="遮罩色", bg="#000000", 
                                              fg="white", relief="raised", width=8, font=("Arial", 8))
        self.app.mask_color_preview.pack(side=tk.LEFT, padx=(0, 2))
        
        tk.Button(mask_props_row, text="选择", command=self._choose_mask_color, 
                 width=6, font=("Arial", 8)).pack(side=tk.LEFT)
        
        # 标注操作按钮
        annotation_frame = tk.LabelFrame(parent, text="标注操作", padx=5, pady=5)
        annotation_frame.pack(fill="x", pady=5)
        
        tk.Button(annotation_frame, text="添加文字标注", command=self.app.add_label,
                 bg="#4CAF50", fg="white", relief="raised").pack(fill="x", pady=1)
        
        # 标线按钮行 - 两个按钮并排
        line_buttons_frame = tk.Frame(annotation_frame)
        line_buttons_frame.pack(fill="x", pady=1)
        
        self.app.straight_line_btn = tk.Button(line_buttons_frame, text="直线模式", 
                                              command=lambda: self._toggle_line_mode("straight"),
                                              bg="#2196F3", fg="white", relief="raised")
        self.app.straight_line_btn.pack(side=tk.LEFT, fill="x", expand=True, padx=(0, 1))
        
        self.app.polyline_btn = tk.Button(line_buttons_frame, text="折线模式", 
                                         command=lambda: self._toggle_line_mode("polyline"),
                                         bg="#2196F3", fg="white", relief="raised")
        self.app.polyline_btn.pack(side=tk.LEFT, fill="x", expand=True, padx=(1, 0))
        
        # 遮罩模式按钮
        self.app.mask_btn = tk.Button(annotation_frame, text="遮罩模式", 
                                     command=self.app.toggle_mask_mode,
                                     bg="#FF9800", fg="white", relief="raised")
        self.app.mask_btn.pack(fill="x", pady=1)
        
        tk.Button(annotation_frame, text="删除选中项", command=self.app.delete_selected,
                 bg="#f44336", fg="white", relief="raised").pack(fill="x", pady=1)
        
        tk.Button(annotation_frame, text="一键清空所有", command=self.app.clear_all_annotations,
                 bg="#e91e63", fg="white", relief="raised").pack(fill="x", pady=1)
        
        # 图片控制按钮
        image_frame = tk.LabelFrame(parent, text="图片控制", padx=5, pady=5)
        image_frame.pack(fill="x", pady=5)
        
        # 缩放控制 - 使用网格布局
        zoom_frame = tk.Frame(image_frame)
        zoom_frame.pack(fill="x", pady=2)
        
        tk.Button(zoom_frame, text="放大 (+)", command=lambda: self.app.event_handlers.zoom(1.2),
                 bg="#FF9800", fg="white", width=10).pack(side=tk.LEFT, padx=1)
        tk.Button(zoom_frame, text="缩小 (-)", command=lambda: self.app.event_handlers.zoom(0.8),
                 bg="#FF9800", fg="white", width=10).pack(side=tk.LEFT, padx=1)
        tk.Button(zoom_frame, text="自适应", command=self.app.fit_to_window,
                 bg="#9C27B0", fg="white", width=10).pack(side=tk.LEFT, padx=1)
        
        # 显示当前缩放比例
        self.app.zoom_label = tk.Label(image_frame, text="缩放: 100%", bg="#f0f0f0", fg="#666666")
        self.app.zoom_label.pack(pady=2)

    def _build_manage_settings(self, parent):
        """构建标注管理面板 - 右侧3个列表"""
        # 文字标注列表
        label_frame = tk.LabelFrame(parent, text="文字标注列表", padx=3, pady=3, 
                                   font=("Arial", 9, "bold"))
        label_frame.pack(fill="both", expand=True, pady=(0, 3))
        
        self.app.label_list = tk.Listbox(label_frame, font=("Arial", 8),
                                         selectbackground="#ff4444", selectforeground="white",
                                         bg="#f8f9fa", fg="#333333",
                                         selectmode=tk.SINGLE, activestyle="dotbox", 
                                         highlightthickness=0, relief="flat")
        scrollbar1 = tk.Scrollbar(label_frame, orient="vertical", command=self.app.label_list.yview)
        self.app.label_list.configure(yscrollcommand=scrollbar1.set)
        
        self.app.label_list.pack(side="left", fill="both", expand=True)
        scrollbar1.pack(side="right", fill="y")
        self.app.label_list.bind("<<ListboxSelect>>", self.app.on_label_list_select)
        
        # 线条标注列表
        line_frame = tk.LabelFrame(parent, text="线条标注列表", padx=3, pady=3, 
                                  font=("Arial", 9, "bold"))
        line_frame.pack(fill="both", expand=True, pady=3)
        
        self.app.line_list = tk.Listbox(line_frame, font=("Arial", 8),
                                        selectbackground="#ff4444", selectforeground="white",
                                        bg="#f8f9fa", fg="#333333",
                                        selectmode=tk.SINGLE, activestyle="dotbox",
                                        highlightthickness=0, relief="flat")
        scrollbar2 = tk.Scrollbar(line_frame, orient="vertical", command=self.app.line_list.yview)
        self.app.line_list.configure(yscrollcommand=scrollbar2.set)
        
        self.app.line_list.pack(side="left", fill="both", expand=True)
        scrollbar2.pack(side="right", fill="y")
        self.app.line_list.bind("<<ListboxSelect>>", self.app.on_line_list_select)
        
        # 遮罩管理列表
        mask_frame = tk.LabelFrame(parent, text="遮罩管理", padx=3, pady=3, 
                                  font=("Arial", 9, "bold"))
        mask_frame.pack(fill="both", expand=True, pady=(3, 0))
        
        self.app.mask_list = tk.Listbox(mask_frame, font=("Arial", 8),
                                       selectbackground="#ff4444", selectforeground="white",
                                       bg="#f8f9fa", fg="#333333",
                                       selectmode=tk.SINGLE, activestyle="dotbox",
                                       highlightthickness=0, relief="flat")
        scrollbar3 = tk.Scrollbar(mask_frame, orient="vertical", command=self.app.mask_list.yview)
        self.app.mask_list.configure(yscrollcommand=scrollbar3.set)
        
        self.app.mask_list.pack(side="left", fill="both", expand=True)
        scrollbar3.pack(side="right", fill="y")
        self.app.mask_list.bind("<<ListboxSelect>>", self.app.on_mask_list_select)

    def _get_font_names(self):
        """获取可用字体名称列表"""
        font_names = []
        for font_path in self.app.available_fonts:
            font_name = os.path.basename(font_path)
            font_names.append(font_name)
        return font_names

    def _add_custom_font(self):
        """添加自定义字体"""
        from tkinter import filedialog, messagebox
        
        # 打开文件选择对话框
        font_path = filedialog.askopenfilename(
            title="选择字体文件",
            filetypes=[
                ("字体文件", "*.ttf;*.ttc;*.otf"),
                ("TrueType字体", "*.ttf"),
                ("TrueType集合", "*.ttc"),
                ("OpenType字体", "*.otf"),
                ("所有文件", "*.*")
            ]
        )
        
        if not font_path:
            return
            
        # 检查文件是否存在
        if not os.path.exists(font_path):
            messagebox.showerror("错误", "选择的字体文件不存在！")
            return
            
        # 检查是否已经添加过这个字体
        if font_path in self.app.available_fonts:
            messagebox.showinfo("提示", "这个字体已经在列表中了！")
            return
            
        # 添加到字体列表
        self.app.available_fonts.append(font_path)
        
        # 更新下拉框
        self.app.font_combo['values'] = self._get_font_names()
        
        # 自动选择新添加的字体
        font_name = os.path.basename(font_path)
        self.app.font_var.set(font_name)
        self.app.current_font_path = font_path
        
        # 如果有选中的标注，更新其字体
        if self.app.selected_label:
            self.app.event_handlers.update_selected_label()
            
        messagebox.showinfo("成功", f"字体 '{font_name}' 添加成功！")

    def _choose_line_color(self):
        """选择线条颜色"""
        from tkinter import colorchooser
        color = colorchooser.askcolor(color=self.app.line_color_preview["bg"])[1]
        if color:
            self.app.line_color_preview.configure(bg=color)
            self.app.line_color = color
            # 如果有选中的线条，更新其颜色
            if self.app.selected_line:
                self.app.event_handlers.update_selected_line()

    def _toggle_line_mode(self, line_type):
        """切换标线模式"""
        if self.app.line_mode and self.app.line_type == line_type:
            # 如果当前模式已开启，则关闭
            self.app.line_mode = False
            self.app.line_type = None
            self._update_line_buttons()
            self.app.event_handlers.clear_temp_line_state()
        else:
            # 开启指定模式
            self.app.line_mode = True
            self.app.line_type = line_type
            self.app.line_type_var.set(line_type)
            self._update_line_buttons()
            self.app.event_handlers.clear_temp_line_state()

    def _update_line_buttons(self):
        """更新标线按钮状态"""
        if hasattr(self.app, 'straight_line_btn') and hasattr(self.app, 'polyline_btn'):
            if self.app.line_mode:
                if self.app.line_type == "straight":
                    self.app.straight_line_btn.configure(text="直线模式 ●", bg="#1976D2")
                    self.app.polyline_btn.configure(text="折线模式", bg="#2196F3")
                elif self.app.line_type == "polyline":
                    self.app.straight_line_btn.configure(text="直线模式", bg="#2196F3")
                    self.app.polyline_btn.configure(text="折线模式 ●", bg="#1976D2")
            else:
                self.app.straight_line_btn.configure(text="直线模式", bg="#2196F3")
                self.app.polyline_btn.configure(text="折线模式", bg="#2196F3")

    def _choose_mask_color(self):
        """选择遮罩颜色"""
        from tkinter import colorchooser
        color = colorchooser.askcolor(color=self.app.mask_color_preview["bg"])[1]
        if color:
            self.app.mask_color_preview.configure(bg=color)
            self.app.mask_color = color
            # 如果有选中的遮罩，更新其颜色
            if self.app.selected_mask:
                self.app.update_selected_mask()

    def _update_mask_button_state(self):
        """更新遮罩按钮状态"""
        if hasattr(self.app, 'mask_btn'):
            if self.app.mask_mode:
                self.app.mask_btn.configure(text="遮罩模式 ●", bg="#F57C00")
            else:
                self.app.mask_btn.configure(text="遮罩模式", bg="#FF9800")

